package com.base.dataStructure.linkedlist;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Iterator;
import java.util.function.Consumer;

/**
 * @Author: hdhao
 * @Create: 2023/3/27 - 19:23
 * @Version: v1.0
 */
//单项链表类
public class SinglyLinkedListSentinel implements Iterable<Integer>{//整体
    //头指针指向哨兵节点
    private Node head = new Node(666,null);

    @Override
    public Iterator<Integer> iterator() {
        return new Iterator<Integer>() {
            Node p = head.next;
            @Override
            public boolean hasNext() {
                return p != null;
            }

            @Override
            public Integer next() {//返回当前值，并指向下一个元素
                int v = p.value;
                p = p.next;
                return v;
            }
        };
    }


    /**
     * 节点类
     */
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    private static class Node{
        int value;//值
        Node next;//下一个节点指针
    }

    /**
     * 向链表的头结点位置添加元素
     * @param value
     */
    public void addFirst(int value){
        //1.链表为空的情况
        //head = new Node(value,null);
        //2.链表非空的情况
        //head = new Node(value,head);
        insert(0,value);
    }

    /**
     * while循环遍历链表
     * @param consumer
     */
    public void loop1(Consumer<Integer> consumer){
        Node p = head;
        while (p != null){
            //输出当前节点的值
            consumer.accept(p.value);
            //让指针指向下一节点
            p = p.next;
        }
    }

    /**
     * for循环遍历链表
     * @param consumer
     */
    public void loop2(Consumer<Integer> consumer){
        for (Node p = head; p != null; p=p.next){
            consumer.accept(p.value);
        }
    }

    /**
     * 寻找链表尾部节点
     * @return
     */
    private Node findLast(){
        //判断空链表情况
//        if (head == null){
//            return null;
//        }
        Node p;
        for (p = head; p.next != null; p=p.next){

        }
        return p;
    }

    /**
     * 向链表尾部添加节点
     * @param value
     */
    public void addLast(int value){
        Node last = findLast();
        //当加入哨兵节点后,最后一个节点永远不可能为空了
//        if (last == null){
//            addFirst(value);
//        }
        last.next = new Node(value,null);
    }

    public void test(){
        int i = 0;
        for (Node p = head; p != null; p = p.next,i++){
            System.out.println(p.value+"索引是:"+i);
        }
    }

    /**
     * 找到索引index 对应的node节点
     * @param index
     * @return
     */
    private Node findNode(int index){
        int i = -1;
        for (Node p = head; p != null; p = p.next,i++){
            if (i == index){
                return p;
            }
        }
        return null;//没找到
    }

    /**
     * 根据索引位置找到对应的值
     * @param index
     * @return
     */
    public int get(int index){
        Node node = findNode(index);
        if (node == null){
            throw new IllegalArgumentException(String.format("idnex [%d] illegal",index));
        }else {
            return node.value;
        }
    }

    public void insert(int index,int value){
//        if (index == 0){
//            addFirst(value);
//            return;
//        }
        //找到上一个节点
        Node prev = findNode(index - 1);
//        if (prev == null){
//            throw new IllegalArgumentException(String.format("idnex [%d] illegal",index));
//        }
        prev.next = new Node(value, prev.next);
    }

    public void removeFirst(){
//        if (head == null){
//            throw new RuntimeException("链表为空,不能删除");
//        }
        //head = head.next;
        remove(0);
    }

    /**
     * 根据索引删除
     * @param index
     */
    public void remove(int index){
//        if (index == 0){
//            removeFirst();
//            return;
//        }
        //上一个节点
        Node prev = findNode(index - 1);
        if (prev == null){
            throw new RuntimeException("index is illegal");
        }
        //需要被删除的节点
        Node removed = prev.next;
        if (removed == null){
            throw new RuntimeException("index is illegal");
        }
        prev.next = removed.next;

    }

}


